//
// Created by v on 19-7-8.
//

#include "CMConfigSimpleJson.h"
#include "utils/cm_utils.h"

CMConfigSimpleJson::CMConfigSimpleJson() { m_valid = false; }

CMConfigSimpleJson::CMConfigSimpleJson(const char *filename)
{
    char *data = NULL;
    int   len  = 0;
    m_valid    = false;
    m_filename = filename;
    if (m_filename.empty())
    {
        m_root.SetObject();
        return;
    }
    int ret = cm_read_file_data(filename, &data, &len);
    if (ret > 0)
    {
        m_root.Parse<0>(data);
        if (!m_root.GetParseError())
        {
            m_valid = true;
        }
        else
        {
            m_root.SetObject();
        }
    }
    else
    {
        m_root.SetObject(); // init
    }
    if (data)
        free(data);
}

CMConfigSimpleJson::CMConfigSimpleJson(const std::string &buffer)
{
    m_valid = false;
    m_root.Parse<0>(buffer.c_str());
    if (!m_root.GetParseError())
    {
        m_valid = true;
    }
    else
    {
        m_root.SetObject();
    }
}

CMConfigSimpleJson::CMConfigSimpleJson(const rapidjson::Value &root)
{
    m_valid = false;
    rapidjson::StringBuffer                    buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    bool                                       ret = root.Accept(writer);
    if (ret)
    {
        m_root.Parse<0>(buffer.GetString());
        if (!m_root.GetParseError())
        {
            m_valid = true;
        }
        else
        {
            m_root.SetObject();
        }
    }
    else
    {
        m_root.SetObject();
    }
}

int CMConfigSimpleJson::open(const char *filename)
{
    char *data = NULL;
    int   len  = 0;
    m_valid    = false;
    m_filename = filename;
    if (m_filename.empty())
    {
        m_root.SetObject();
        return -1;
    }
    int ret = cm_read_file_data(filename, &data, &len);
    if (ret > 0)
    {
        m_root.Parse<0>(data);
        if (!m_root.GetParseError())
        {
            m_valid = true;
        }
        else
        {
            m_root.SetObject();
        }
    }
    else
    {
        m_root.SetObject(); // init
    }
    return 0;
}

int CMConfigSimpleJson::open(const std::string &buffer)
{
    m_valid = false;
    m_root.Parse<0>(buffer.c_str());
    if (!m_root.GetParseError())
    {
        m_valid = true;
    }
    else
    {
        m_root.SetObject();
    }
    return 0;
}

int CMConfigSimpleJson::getGeneralString(const char *key, std::string &result)
{
    if (!m_valid)
        return -1;
    if (m_root.HasMember(key) && m_root[key].IsString())
    {
        result = m_root[key].GetString();
        return 0;
    }
    return -2;
}

int CMConfigSimpleJson::getGeneralBool(const char *key, bool &result)
{
    if (!m_valid)
        return -1;
    if (m_root.HasMember(key) && m_root[key].IsBool())
    {
        result = m_root[key].GetBool();
        return 0;
    }
    return -2;
}

int CMConfigSimpleJson::getGeneralInt(const char *key)
{
    if (!m_valid)
        return -1;
    if (m_root.HasMember(key) && m_root[key].IsInt())
    {
        return m_root[key].GetInt();
    }
    return -2;
}

int CMConfigSimpleJson::setGeneralString(rapidjson::Value &obj, const char *key,
                                         const char *value)
{
    if (obj.HasMember(key))
    {
        obj.RemoveMember(key);
    }
    obj.AddMember(rapidjson::StringRef(key, strlen(key)),
                  rapidjson::Value().SetString(value, m_root.GetAllocator()),
                  m_root.GetAllocator());
    return 0;
}

int CMConfigSimpleJson::setGeneralInt(rapidjson::Value &obj, const char *key,
                                      int value)
{
    if (obj.HasMember(key))
    {
        obj.RemoveMember(key);
    }
    obj.AddMember(rapidjson::StringRef(key, strlen(key)),
                  rapidjson::Value().SetInt(value), m_root.GetAllocator());
    return 0;
}

int CMConfigSimpleJson::setGeneralBool(rapidjson::Value &obj, const char *key,
                                       bool value)
{
    if (obj.HasMember(key))
    {
        obj.RemoveMember(key);
    }
    obj.AddMember(rapidjson::StringRef(key, strlen(key)),
                  rapidjson::Value().SetBool(value), m_root.GetAllocator());
    return 0;
}

int CMConfigSimpleJson::setGeneralInt64(rapidjson::Value &obj, const char *key,
                                        int64_t value)
{
    if (obj.HasMember(key))
    {
        obj.RemoveMember(key);
    }
    obj.AddMember(rapidjson::StringRef(key, strlen(key)),
                  rapidjson::Value().SetInt64(value), m_root.GetAllocator());
    return 0;
}

int CMConfigSimpleJson::generateString(std::string &result)
{
    rapidjson::StringBuffer                    buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    bool                                       ret = m_root.Accept(writer);
    if (ret)
    {
        result = buffer.GetString();
    }
    return 0;
}

int CMConfigSimpleJson::writeBack(const char *filename)
{
    std::string fn = m_filename;
    if (filename)
    {
        fn = filename;
    }
    if (fn.empty())
        return -1;
    rapidjson::StringBuffer                    buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    bool                                       ret = m_root.Accept(writer);
    if (ret)
    {
        ret = cm_write_file_data(fn.c_str(), (char *)buffer.GetString(),
                                 buffer.GetSize());
        if (ret > 0)
            return ret;
    }
    return -2;
}
